#include "VSSkelectonMeshNode.h"
#include "VSBoneNode.h"
#include "VSAnimTree.h"
#include "VSGraphicInclude.h"
#include "VSStream.h"
using namespace VSEngine2;
IMPLEMENT_RTTI(VSSkelectonMeshNode,VSModelMeshNode)
BEGIN_ADD_PROPERTY(VSSkelectonMeshNode,VSModelMeshNode)
REGISTER_PROPERTY(m_pSkelecton,Skelecton,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pAnimSet,AnimSet,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pAnimSequence,AnimSequence,VSProperty::F_CLONE)
END_ADD_PROPERTY
IMPLEMENT_INITIAL_BEGIN(VSSkelectonMeshNode)
IMPLEMENT_INITIAL_END
VSSkelectonMeshNodePtr VSSkelectonMeshNode::Default = NULL;
bool VSSkelectonMeshNode::ms_bIsEnableASYNLoader = true;
bool VSSkelectonMeshNode::ms_bIsEnableGC = true;
VSSkelectonMeshNode::VSSkelectonMeshNode()
{
	m_pSkelecton = NULL;
	m_pAnimSet = NULL;
	m_pAnimSequence = NULL;
}
VSSkelectonMeshNode::~VSSkelectonMeshNode()
{
	m_pSkelecton = NULL;
	m_pAnimSet = NULL;
	m_pAnimSequence = NULL;
}
unsigned int VSSkelectonMeshNode::DiskUse()const
{
	unsigned int Used = VSModelMeshNode::DiskUse();

	Used +=sizeof(VSSkelecton *);
	VSString FileName;
	if (m_pAnimSet)
	{
		FileName = m_pAnimSet->GetResourceName().GetString();
	}
	Used += VSStream::GetStrDistUse(FileName);	

	return Used;
}
bool VSSkelectonMeshNode::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSModelMeshNode::Save(rStream,iSaveUse))
		return 0;




// 	VSSkelecton * pSkelecton = m_pSkelecton;
// 	if(!rStream.Write(&pSkelecton,sizeof(VSSkelecton *)))
// 		return 0;
	if(!rStream.WriteObjectPtr(m_pSkelecton))
		return 0;
	iSaveUse += sizeof(VSSkelecton *);


	VSString FileName;
	if (m_pAnimSet)
	{
		FileName = m_pAnimSet->GetResourceName().GetString();
	}
	if(!rStream.WriteString(FileName))
		return 0;
	iSaveUse += VSStream::GetStrDistUse(FileName);
	return 1;
}
bool VSSkelectonMeshNode::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSModelMeshNode::Load(rStream,iSaveUse))
		return 0;




// 	VSSkelecton * pSkelecton;
// 	if(!rStream.Read(&pSkelecton,sizeof(VSSkelecton *)))
// 		return 0;
// 	AddLink(pSkelecton);
	if(!rStream.ReadObjectPtr(m_pSkelecton))
		return 0;
	iSaveUse += sizeof(VSSkelecton *);


	VSString FileName;
	if(!rStream.ReadString(FileName))
		return 0;
	m_pAnimSet = VSResourceManager::LoadAnimSet(FileName.GetBuffer());

	iSaveUse += VSStream::GetStrDistUse(FileName);
	return 1;
}
bool VSSkelectonMeshNode::Link(VSStream & rStream)
{
	if(!VSModelMeshNode::Link(rStream))
		return 0;

	//m_pSkelecton = (VSSkelecton *)rStream.GetMapValue(GetNextLink());
	rStream.LinkObjectPtr(m_pSkelecton);
	return 1;

}
bool VSSkelectonMeshNode::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSSkelectonMeshNode* Temp = DynamicCast<VSSkelectonMeshNode>(pObject); 
	if(!Temp)
		return 0;

	VSSkelecton * pTemp1  = Temp->m_pSkelecton;
	VSSkelecton * pTemp2 =(VSSkelecton *)VSObject::GetInstance((pTemp1)->GetType().GetName());
	pTemp2->Clone(pTemp1,uiType);
	m_pSkelecton = pTemp2;
	m_pSkelecton->m_pParent = this;
	if(VSModelMeshNode::Clone(pObject,uiType))
	{
		m_pAnimSet = Temp->m_pAnimSet;
		if (Temp->m_pAnimSequence)
		{
			VSAnimSequenceFunc * pAnimSe = VS_NEW VSAnimSequenceFunc(this);
			pAnimSe->Clone(Temp->m_pAnimSequence,uiType);
			m_pAnimSequence = pAnimSe;
		}

	}
	else
		return 0;
	return 1;


}
bool VSSkelectonMeshNode::Register(VSStream & rStream)const
{
	if (rStream.IsObjectRegister(this))
	{
		return 1;
	}
	if(!VSModelMeshNode::Register(rStream))
		return 0;
	if(m_pSkelecton)
	{
		if(!m_pSkelecton->Register(rStream))
			return 0;

	}
	return 1;
}
void VSSkelectonMeshNode::SetSkelecton(VSSkelecton * pSkelecton)
{	
	if(m_pSkelecton)
	{
		m_pSkelecton->m_pParent = NULL;
	}
	m_pSkelecton = pSkelecton;
	m_pSkelecton->m_pParent = this;
	
}
void VSSkelectonMeshNode::SetAnimSet(VSAnimSet * pAnimSet)
{
	if (m_pAnimSet == pAnimSet)
	{
		return;
	}
	m_pAnimSet = pAnimSet;
	for (unsigned int i = 0 ; i < m_ControllerArray.GetNum() ; i++)
	{
		VSAnimTree * pAnimTree = DynamicCast<VSAnimTree>(m_ControllerArray[i]);
		if (pAnimTree)
		{
			pAnimTree->ResetAnimFunction();
		}
	}
}
void VSSkelectonMeshNode::UpdateNodeAll(double dAppTime)
{

	if (!m_bEnable)
	{
		return;
	}
	if (dAppTime > 0.0f)
	{
		UpdateController(dAppTime);
	}
	

	UpdateTransform(dAppTime);



	if(m_pSkelecton)
	{
		if (!m_bIsStatic || m_pSkelecton->m_bIsDrawSkelecton)
		{
			m_pSkelecton->UpdateNodeAll(dAppTime);
		}


	}
	

	
	for (unsigned int i = 0; i < m_pChild.GetNum(); i++)	
	{ 
		if (m_pChild[i]) 
			m_pChild[i]->UpdateNodeAll(dAppTime); 
	} 


	UpdateLightState(dAppTime);





	UpdateCameraState(dAppTime);

	if (dAppTime > 0.0f)
	{
		UpdateOther(dAppTime);
	}


	if(m_bIsChanged)
	{
		UpdateWorldBound(dAppTime); 
	}
	m_bIsChanged = false;

}
void VSSkelectonMeshNode::ComputeNodeVisibleSet(VSCuller & Culler,bool bNoCull,double dAppTime)
{

	UpDateView(Culler,dAppTime);
	for(unsigned int i = 0 ; i < m_pChild.GetNum() ; i++)
	{
		if(m_pChild[i])
		{

			m_pChild[i]->ComputeVisibleSet(Culler,bNoCull,dAppTime);


		}

	}
	m_pSkelecton->ComputeNodeVisibleSet(Culler,bNoCull,dAppTime);

}
void VSSkelectonMeshNode::UpdateWorldBound(double dAppTime)
{
	bool bFoundFirstBound = false; 
	for (unsigned int i = 0; i < m_pChild.GetNum(); i++) 
	{ 	
		if(m_pChild[i])
		{
			if(!bFoundFirstBound)
			{
				m_WorldBV = m_pChild[i]->m_WorldBV;
				bFoundFirstBound = true; 
			}
			else
			{

				m_WorldBV = m_WorldBV.MergAABB(m_pChild[i]->m_WorldBV);
			}
		}

	} 
	if(!bFoundFirstBound)
	{
		m_WorldBV = m_pSkelecton->m_WorldBV;
		bFoundFirstBound = true; 
	}
	else
	{
		m_WorldBV = m_WorldBV.MergAABB(m_pSkelecton->m_WorldBV);
	}
}
void VSSkelectonMeshNode::UpDateView(VSCuller & Culler,double dAppTime)
{
	VSModelMeshNode::UpDateView(Culler,dAppTime);
	VSCamera * pCamera = Culler.GetCamera();
	if (!pCamera)
	{
		return ;
	}
	for (unsigned int i = 0 ; i < m_pChild.GetNum() ; i++)
	{
		if (m_pChild[i])
		{
			m_pChild[i]->UpDateView(Culler,dAppTime);
		}
	}
	
}
bool VSSkelectonMeshNode::PlayAnim(const VSString & AnimName,float fRatio,unsigned int uiRepeatType)
{
	if (m_pAnimSequence == NULL)
	{
		m_pAnimSequence = VS_NEW VSAnimSequenceFunc(this);
		if (m_pAnimSequence)
		{
			m_bIsStatic = false;
		}
		//AddController(m_pAnimSequence);

	}
	m_pAnimSequence->SetAnim(AnimName);
	m_pAnimSequence->m_uiRepeatType = uiRepeatType;
	m_pAnimSequence->m_dFrequency = fRatio;

	return 1;;
}
void VSSkelectonMeshNode::UpdateController(double dAppTime)
{
	VSModelMeshNode::UpdateController(dAppTime);
	if(m_pAnimSequence)
	{
		m_pAnimSequence->ClearFlag();
		m_pAnimSequence->Update(dAppTime);
		m_pAnimSequence->UpDateBone();
	}

}
